﻿using System;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using CodeContrib;
using CodeContrib.Web.Mvc;
using CodeContribBlog.Data;
using CodeContribBlog.Web.Mvc.ViewModels;

namespace CodeContribBlog.Web.Mvc.Controllers
{
	public class PostController : BlogController
	{
		public ActionResult Archive(int year, int? month, int? day, Paging paging)
		{
			var query = BlogContext.Posts
				.WhereIsPublic()
				.Where(p => p.PublishedAt.Year == year)
				.Include(p => p.Author)
				.Include(p => p.Comments)
				.Include(p => p.Tags);

			if (month != null)
			{
				query = query.Where(p => p.PublishedAt.Month == month.Value);
			}

			if (day != null)
			{
				query = query.Where(p => p.PublishedAt.Day == day.Value);
			}

			var posts = query.OrderByDescending(p => p.PublishedAt).ToPaged(paging);

			return View("List", posts);
		}

		[ActionName("Details")]
		[HttpPost]
		[ValidateAntiForgeryToken]
		[ValidateCaptcha]
		public ActionResult Comment(int id, string slug, Guid? showIfPrivate)
		{
			var comment = new Comment
				              {
					              PostId = id
				              };

			TryUpdateModel(comment, "Comment", new[]
				                                   {
					                                   "Author", "EmailAddress", "Url", "Body"
				                                   });

			if (!ModelState.IsValid)
			{
				var result = Details(id, slug, showIfPrivate);
				var model = result as ViewResult;

				if (model != null)
				{
					var viewModel = model.Model as PostViewModel;

					if (viewModel != null)
					{
						viewModel.Comment = comment;
					}
				}

				return result;
			}

			BlogContext.Comments.Add(comment);
			BlogContext.SaveChanges();

			const string successMessage = "Your comment will be posted soon. Thanks!";

			TempData["InfoMessage"] = successMessage;

			return RedirectToAction("Details", Url.PreserveRouteValues());
		}

		public ActionResult Details(int id, string slug, Guid? showIfPrivate)
		{
			var post = BlogContext.Posts
				.Select(p => new
					             {
						             Posts = p,
						             Comments = p.Comments.Where(c => !c.IsSpam)
					             })
				.Select(x => x.Posts)
				.Include(p => p.Author)
				.Include(x => x.Blog)
				.Include(p => p.Comments)
				.Include(p => p.Tags)
				.SingleOrDefault(p => p.Id == id);

			if (post == null || post.IsDeleted
			    || post.PublishedAt > DateTime.UtcNow)
			{
				return new NotFoundResult();
			}

			if (post.Slug != slug)
			{
				return RedirectToActionPermanent("Details", new
					                                            {
						                                            id,
						                                            post.Slug
					                                            });
			}

			var viewModel = new PostViewModel
				                {
					                NextPost = BlogContext.FindNextPost(post),
					                Post = post,
					                PreviousPost = BlogContext.FindPreviousPost(post)
				                };

			SetCommenter(viewModel);

			return View("Details", viewModel);
		}

		public ActionResult List(Paging paging)
		{
			var posts = BlogContext.Posts
				.WhereIsPublic()
				.OrderByDescending(p => p.PublishedAt)
				.Include(p => p.Author)
				.Include(p => p.Comments)
				.Include(p => p.Tags)
				.ToPaged(paging);

			return View("List", posts);
		}

		private void SetCommenter(PostViewModel viewModel)
		{
			if (User != null)
			{
				viewModel.Comment = new Comment
					                    {
						                    Author = User.Name,
						                    EmailAddress = User.EmailAddress,
						                    Url = Url.AbsoluteRouteUrl("BlogHome")
					                    };
				viewModel.IsLoggedInCommenter = true;
				viewModel.IsTrustedCommenter = true;

				return;
			}

			var cookie = Request.Cookies["Commenter"];

			if (cookie == null)
			{
				return;
			}

			var commenter = BlogContext.Commenters.FindByKey(cookie.Value);

			if (commenter == null)
			{
				Response.Cookies.Set(new HttpCookie("Commeter")
					                     {
						                     Expires = DateTime.Now.AddYears(-1)
					                     });

				return;
			}

			viewModel.Comment = new Comment
				                    {
					                    Author = commenter.Name,
					                    EmailAddress = commenter.EmailAddress,
					                    Url = commenter.Url
				                    };
			viewModel.IsLoggedInCommenter = !string.IsNullOrWhiteSpace(commenter.OpenId);
			viewModel.IsTrustedCommenter = commenter.IsTrusted;
		}

		public ActionResult Tag(string slug, Paging paging)
		{
			var query = BlogContext.Posts
				.WhereIsPublic()
				.Where(p => p.Tags.Select(t => t.Slug)
					            .Contains(slug))
				.OrderByDescending(p => p.PublishedAt)
				.Include(p => p.Author)
				.Include(p => p.Tags)
				.ToPaged(paging);

			return View("List", query);
		}
	}
}